
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       bl_flash.c
  * @author     baiyang
  * @date       2023-4-24
  ******************************************************************************
  */

/*----------------------------------include-----------------------------------*/
#include <stdbool.h>

#include "board.h"
#include <bl/support.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/

/*---------------------------------prototype----------------------------------*/

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
inline void arch_flash_lock(void)
{
    EFM_FWMC_Cmd(DISABLE);
    EFM_REG_Lock();
    EFM_SequenceSectorOperateCmd(BOARD_FIRST_FLASH_SECTOR_TO_ERASE, SOC_FLASH_SECTORS - BOARD_FIRST_FLASH_SECTOR_TO_ERASE, DISABLE);
}

inline void arch_flash_unlock(void)
{
    EFM_REG_Unlock();
    EFM_FWMC_Cmd(ENABLE);
    EFM_SequenceSectorOperateCmd(BOARD_FIRST_FLASH_SECTOR_TO_ERASE, SOC_FLASH_SECTORS - BOARD_FIRST_FLASH_SECTOR_TO_ERASE, ENABLE);
}

inline void arch_setvtor(uint32_t address)
{
    SCB->VTOR = address;
}

uint32_t
flash_func_sector_size(unsigned sector)
{
    if (sector < SOC_FLASH_SECTORS) {
        return HC32_FLASH_PAGE_SIZE;
    }

    return 0;
}

void
flash_func_erase_sector(unsigned sector)
{
    if (sector >= SOC_FLASH_SECTORS || sector < BOARD_FIRST_FLASH_SECTOR_TO_ERASE) {
        return;
    }

    /* Caculate the logical base address of the sector
     * flash_func_read_word will add APP_LOAD_ADDRESS
     */
    uint32_t address = 0;

    for (unsigned i = BOARD_FIRST_FLASH_SECTOR_TO_ERASE; i < sector; i++) {
        address += flash_func_sector_size(i);
    }

    /* blank-check the sector */
    unsigned size = flash_func_sector_size(sector);
    bool blank = true;

    for (unsigned i = 0; i < size; i += sizeof(uint32_t)) {
        if (flash_func_read_word(address + i) != 0xffffffff) {
            blank = false;
            break;
        }
    }

    /* erase the sector if it failed the blank check */
    if (!blank) {
        EFM_SectorErase(address+APP_LOAD_ADDRESS);
    }
}

void
flash_func_write_word(uint32_t address, uint32_t word)
{
    EFM_ProgramWord(address + APP_LOAD_ADDRESS, word);
}

uint32_t
flash_func_read_word(uint32_t address)
{
    if (address & 3) {
        return 0;
    }

    return *(uint32_t *)(address + APP_LOAD_ADDRESS);
}

uint32_t
flash_func_read_otp(uint32_t address)
{
#ifndef OTP_SIZE
    return 0;
#else
    if (idx & 3) {
        return 0;
    }

    if (idx > OTP_SIZE) {
        return 0;
    }

    return *(uint32_t *)(idx + OTP_BASE);
#endif
}

uint32_t
flash_func_read_sn(uint32_t address)
{
    // read a byte out from unique chip ID area
    // it's 12 bytes, or 3 words.
    return *(uint32_t *)(address + SOC_UDID_START_ADDRESS);
}
/*------------------------------------test------------------------------------*/


